package my.stone.asetdemo.ui.widget.motion

import android.content.Context
import android.util.AttributeSet
import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.constraintlayout.motion.widget.TransitionAdapter
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeout
import java.lang.IllegalArgumentException
import java.util.concurrent.CopyOnWriteArrayList
import kotlin.coroutines.resume

open class MultiListenerMotionLayout @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : MotionLayout(context, attrs, defStyleAttr) {

    private val listeners = CopyOnWriteArrayList<TransitionListener>()

    init {
        super.setTransitionListener(object : TransitionListener {
            override fun onTransitionStarted(
                motionLayout: MotionLayout?,
                startId: Int,
                endId: Int
            ) {
                listeners.forEach {
                    it.onTransitionStarted(motionLayout, startId, endId)
                }
            }

            override fun onTransitionChange(
                motionLayout: MotionLayout?,
                startId: Int,
                endId: Int,
                progress: Float
            ) {
                listeners.forEach {
                    it.onTransitionChange(motionLayout, startId, endId, progress)
                }
            }

            override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) {
                listeners.forEach {
                    it.onTransitionCompleted(motionLayout, currentId)
                }
            }

            override fun onTransitionTrigger(
                motionLayout: MotionLayout?,
                triggerId: Int,
                positive: Boolean,
                progress: Float
            ) {
                listeners.forEach {
                    it.onTransitionTrigger(motionLayout, triggerId, positive, progress)
                }
            }
        })
    }

    suspend fun awaitTransitionComplete(transitionId: Int, timeout: Long = 10000L) {
        var listener: TransitionListener? = null
        try {
            withTimeout(timeout) {
                suspendCancellableCoroutine<Unit> { continuation ->
                    val l = object : TransitionAdapter() {
                        override fun onTransitionCompleted(
                            motionLayout: MotionLayout?,
                            currentId: Int
                        ) {
                            if (currentId == transitionId) {
                                removeTransitionListener(this)
                                continuation.resume(Unit)
                            }
                        }
                    }
                    continuation.invokeOnCancellation {
                        removeTransitionListener(l)
                    }
                    addTransitionListener(l)
                    listener = l
                }
            }
        } catch (exception: TimeoutCancellationException) {
            listener?.let { removeTransitionListener(it) }
            throw CancellationException("动画($transitionId)执行超时了！", exception)
        }
    }

    override fun addTransitionListener(listener: TransitionListener) {
        listeners.add(listener)
    }

    override fun removeTransitionListener(listener: TransitionListener?): Boolean {
        listeners.remove(listener)
        return true
    }

    override fun setTransitionListener(listener: TransitionListener?) {
        throw IllegalArgumentException("setTransitionListener()不可用！请使用add/remove TransitionListener()")
    }

}